package services;

import java.util.Collection;
import java.util.Date;

import javax.transaction.Transactional;

import org.joda.time.Days;
import org.joda.time.Interval;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import repositories.AuctionRepository;
import domain.Actor;
import domain.Auction;
import domain.Customer;
import domain.Painting;

@Service
@Transactional
public class AuctionService {

	// Managed repository

	@Autowired
	private AuctionRepository auctionRepository;

	// Supporting services
	
	@Autowired
	private ActorService actorService;
	
	@Autowired
	private PaintingService paintingService;

	// Simple CRUD methods
	
	public Auction create(Painting painting){
		Assert.notNull(painting);
		
		Auction auction = new Auction();
		Customer creator = (Customer) actorService.findByPrincipal();
		
		auction.setWinningBid(null);
		auction.setCreator(creator);
		auction.setPainting(painting);
		
		return auction;
	}
	
	
	public void save(Auction auction){
		checkPrincipal(auction);
		Assert.notNull(auction);
		
		Interval interval = new Interval(auction.getStartMoment().getTime(), auction.getFinishMoment().getTime());
		int days = Days.daysIn(interval).getDays();
		
		Auction activeAuction = this.findActiveAuctionByPrincipal(); 
		Collection<Painting> paintings = paintingService.findPaintingsByPrincipal();

		Assert.isTrue(auction.getStartMoment().before(auction.getFinishMoment()), "auction.start.before.finish.error");
		Assert.isTrue(auction.getStartMoment().after(new Date()) &&
				auction.getFinishMoment().after(new Date()), "auction.not.future.error");
		
		if(activeAuction != null){
			Assert.isTrue((auction.getStartMoment().after(activeAuction.getStartMoment()) &&
					auction.getStartMoment().after(activeAuction.getFinishMoment())), "auction.another.active.error");
		}
		
		Assert.isTrue(paintings.contains(auction.getPainting()), "auction.not.legal.owner.painting.error");
		
		Assert.isTrue(days >= 1, "auction.at.least.one.day.error");
		
		auctionRepository.save(auction);
	}
	
	public void modify(Auction auction){
		checkPrincipal(auction);
		Assert.notNull(auction);
		
		Collection<Painting> paintings = paintingService.findPaintingsByPrincipal();
		Assert.isTrue(auction.getStartMoment().before(new Date()) &&
				auction.getFinishMoment().before(new Date()));
		
		Assert.isTrue(paintings.contains(auction.getPainting()));

		
		auctionRepository.save(auction);
	}

	// Other business methods
	
	public Auction findActiveAuctionByPrincipal() {
		Customer principal = (Customer) actorService.findByPrincipal();// TODO Auto-generated method stub
		return auctionRepository.findActiveAuctionByPrincipal(principal.getId());
	}


	public void checkPrincipal(Auction auction){
		Assert.notNull(auction);
		Customer principal = (Customer) actorService.findByPrincipal();
		Assert.isTrue(auction.getCreator().equals(principal));
	}
	
	public Collection<Auction> findAllActiveAuctions(){
		return auctionRepository.findAllActiveAuctions();
	}
	
	public Collection<Auction> findPastAuctions(){
		return auctionRepository.findPastAuctions();
	}
	
	public Collection<Auction> findPastAuctionsByPrincipal(){
		Actor principal = actorService.findByPrincipal();
		Assert.isTrue(actorService.findByPrincipal() instanceof Customer);
		Customer customer = (Customer) principal;
		return auctionRepository.findPastAuctionsByPrincipal(customer.getId());
	}
	
	public Collection<Auction> findAllActiveAuctionsCreatedByOtherCustomers(){
		Actor principal = actorService.findByPrincipal();
		Assert.isTrue(actorService.findByPrincipal() instanceof Customer);
		Customer customer = (Customer) principal;
		return auctionRepository.findAllActiveAuctionsCreatedByOtherCustomers(customer.getId());
	}
	
	public Auction findOne(int auctionId){
		return auctionRepository.findOne(auctionId);
	}
	
	public Collection<Auction> findAuctionWithMoreBids(){
		return auctionRepository.findAuctionWithMoreBids();

	}

}
